diff options
Diffstat (limited to 'gcsdk/gcsystemaccess.cpp')
| -rw-r--r-- | gcsdk/gcsystemaccess.cpp | 690 |
1 files changed, 690 insertions, 0 deletions
diff --git a/gcsdk/gcsystemaccess.cpp b/gcsdk/gcsystemaccess.cpp new file mode 100644 index 0000000..3a7d3d9 --- /dev/null +++ b/gcsdk/gcsystemaccess.cpp @@ -0,0 +1,690 @@ +//========= Copyright (c), Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "stdafx.h" +#include "gcsystemaccess.h" +#include "gcjob.h" +#include "gcsdk/gcreportprinter.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +namespace GCSDK +{ + + +static GCConVar gcaccess_enable( "gcaccess_enable", "1", "Kill switch that disables all gcaccess tracking and systems" ); + +DECLARE_GC_EMIT_GROUP( g_EGAccess, access ); + + +//----------------------------------------------------------------------------------------------------------------------------------------- +GCAccessSystem_t GenerateUniqueGCAccessID() +{ + static GCAccessSystem_t s_nID = 0; + return s_nID++; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +// CGCAccessSystem +//----------------------------------------------------------------------------------------------------------------------------------------- + +//a GCAccess system that has been registered +class CGCAccessSystem +{ +public: + //the name of the system for display + CUtlString m_sName; + //the unique ID for this system + GCAccessSystem_t m_nID; + //which actions should be enabled or disabled for this system in particular + uint32 m_nActions; + uint32 m_nSuppressActions; + + struct AccessStats_t + { + AccessStats_t(); + void Add( const AccessStats_t& rhs ); + //how many raw accesses have we had? + uint32 m_nNumValid; + //how many failed because the context didn't have rights? + uint32 m_nNumFail; + //how many failed because the associated ID wasn't valid? + uint32 m_nNumFailID; + }; + + struct TrackedJob_t + { + CUtlString m_sContext; + AccessStats_t m_Stats; + }; + + //which jobs have violated this system access rights + CUtlHashMapLarge< uintp, TrackedJob_t > m_Jobs; +}; + +//----------------------------------------------------------------------------------------------------------------------------------------- +// CGCAccessContext +//----------------------------------------------------------------------------------------------------------------------------------------- + +CGCAccessContext::CGCAccessContext() : + m_nActions( 0 ), + m_nSuppressActions( 0 ) +{ +} + +void CGCAccessContext::Init( const char* pszName, uint32 nActions, uint32 nSuppressActions ) +{ + m_sName = pszName; + m_nActions = nActions; + m_nSuppressActions = nSuppressActions; +} + +void CGCAccessContext::AddSystem( GCAccessSystem_t nSystem ) +{ + m_nSystems.InsertIfNotFound( nSystem ); +} + +bool CGCAccessContext::HasSystem( GCAccessSystem_t system ) const +{ + return ( m_nSystems.Find( system ) != m_nSystems.InvalidIndex() ); +} + +bool CGCAccessContext::IsSubsetOf( const CGCAccessContext& context ) const +{ + FOR_EACH_VEC( m_nSystems, nCurrSystem ) + { + if( !context.HasSystem( m_nSystems[ nCurrSystem ] ) ) + return false; + } + return true; +} + +void CGCAccessContext::AddSystemsFrom( const CGCAccessContext& context ) +{ + FOR_EACH_VEC( context.m_nSystems, nCurrSystem ) + { + AddSystem( context.m_nSystems[ nCurrSystem ] ); + } +} + +void CGCAccessContext::SetAction( EGCAccessAction eAction, bool bSet ) +{ + if( bSet ) + m_nActions |= eAction; + else + m_nActions &= ~( uint32 )eAction; +} + +void CGCAccessContext::SetSuppressAction( EGCAccessAction eAction, bool bSet ) +{ + if( bSet ) + m_nSuppressActions |= eAction; + else + m_nSuppressActions &= ~( uint32 )eAction; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +// CGCAccess +//----------------------------------------------------------------------------------------------------------------------------------------- + +static CGCAccess g_GCAccess; +CGCAccess& GGCAccess() +{ + return g_GCAccess; +} + +CGCAccessSystem::AccessStats_t::AccessStats_t() + : m_nNumFail( 0 ) + , m_nNumFailID( 0 ) + , m_nNumValid( 0 ) +{} + +void CGCAccessSystem::AccessStats_t::Add( const AccessStats_t& rhs ) +{ + m_nNumFail += rhs.m_nNumFail; + m_nNumFailID += rhs.m_nNumFailID; + m_nNumValid += rhs.m_nNumValid; +} + +CGCAccess::CGCAccess() : + m_nActions( GCAccessAction_TrackSuccess | GCAccessAction_TrackFail| GCAccessAction_ReturnFail ), + m_nSuppressActions( 0 ) +{ + m_GlobalContext.Init( "Global" ); +} + +void CGCAccess::RegisterSystem( const char* pszName, GCAccessSystem_t nID, uint32 nActions, uint32 nSupressActions ) +{ + //make sure that we don't have a conflict + int nIndex = m_Systems.Find( nID ); + if( nIndex != m_Systems.InvalidIndex() ) + { + // !FIXME! + // DOTAMERGE AssertMsg varargs + AssertMsg3( false, "Multiple systems conflciting in Register System: ID %d, original: %s, new %s", nID, m_Systems[ nIndex ]->m_sName.String(), pszName ); + return; + } + + CGCAccessSystem* pSystem = new CGCAccessSystem; + pSystem->m_sName = pszName; + pSystem->m_nID = nID; + pSystem->m_nActions = nActions; + pSystem->m_nSuppressActions = nSupressActions; + m_Systems.Insert( nID, pSystem ); +} + +bool CGCAccess::ValidateAccess( GCAccessSystem_t nSystem ) +{ + //global kill switch + if( !gcaccess_enable.GetBool() ) + return true; + + return InternalValidateAccess( nSystem, CSteamID(), CSteamID() ); +} + +bool CGCAccess::ValidateSteamIDAccess( GCAccessSystem_t nSystem, CSteamID steamID ) +{ + //global kill switch + if( !gcaccess_enable.GetBool() ) + return true; + + CSteamID expectedID = ( g_pJobCur ) ? g_pJobCur->SOVALIDATE_GetSteamID() : steamID; + return InternalValidateAccess( nSystem, steamID, expectedID ); +} + +bool CGCAccess::InternalValidateAccess( GCAccessSystem_t nSystem, CSteamID steamID, CSteamID expectedID ) +{ + //see if tracking for this system is disabled. This list is almost always empty, so just use a linear search for now. + FOR_EACH_VEC( m_SuppressAccess, nAction ) + { + if( m_SuppressAccess[ nAction ].m_nSystem == nSystem ) + return true; + } + + //assume the global context + const CGCAccessContext* pContext = &m_GlobalContext; + const char* pszJobName = "[global]"; + + //if we have a job, use it's context + if( g_pJobCur ) + { + const CGCJob* pJob = static_cast< const CGCJob* >( g_pJobCur ); + pszJobName = pJob->GetName(); + if( pJob->GetContext() ) + pContext = pJob->GetContext(); + } + + //is this a valid system to access + bool bValidSteamID = ( steamID == expectedID ); + bool bValidSystem = pContext->HasSystem( nSystem ); + bool bValidAccess = ( bValidSystem && bValidSteamID ); + + //determine the actions we want to do for tracking + uint32 nActions = pContext->GetActions() | m_nActions; + uint32 nSuppressActions = pContext->GetSuppressActions() | m_nSuppressActions; + + //look up the system that we are accessing + CGCAccessSystem* pSystem = NULL; + int nSystemIndex = m_Systems.Find( nSystem ); + if( nSystemIndex == m_Systems.InvalidIndex() ) + { + // !FIXME! DOTAMERGE + // AssertMsg varargs + AssertMsg1( false, "Error: Tracking a system that has not been registered. Make sure to register system %u", nSystem ); + } + else + { + //make sure that we have a stat entry for this job + pSystem = m_Systems[ nSystemIndex ]; + nActions |= pSystem->m_nActions; + nSuppressActions |= pSystem->m_nSuppressActions; + } + + //remove any suppressed actions + nActions &= ~nSuppressActions; + + //see if we need to track this access + bool bTrackSuccess = ( nActions & GCAccessAction_TrackSuccess ) && bValidAccess; + bool bTrackFail = ( nActions & GCAccessAction_TrackFail ) && !bValidAccess; + if( ( bTrackSuccess || bTrackFail ) && pSystem ) + { + //make sure that we have a stat entry for this job + int nJobIndex = pSystem->m_Jobs.Find( ( uintp )pszJobName ); + if( nJobIndex == pSystem->m_Jobs.InvalidIndex() ) + { + nJobIndex = pSystem->m_Jobs.Insert( ( uintp )pszJobName ); + pSystem->m_Jobs[ nJobIndex ].m_sContext = pContext->GetName(); + } + + //update our stats based upon what was valid and what wasn't + CGCAccessSystem::AccessStats_t& stats = pSystem->m_Jobs[ nJobIndex ].m_Stats; + if( bTrackSuccess ) + stats.m_nNumValid++; + + if( bTrackFail ) + { + if( !bValidSteamID ) + stats.m_nNumFailID++; + if( !bValidSystem ) + stats.m_nNumFail++; + } + } + + //see if this is a single access we want to try and track + FOR_EACH_VEC( m_SingleAsserts, nCurrAssert ) + { + SingleAssert_t* pAssert = m_SingleAsserts[ nCurrAssert ]; + if( nSystem == pAssert->m_System ) + { + if( V_stricmp( ( pAssert->m_bContext ) ? pContext->GetName() : pszJobName, pAssert->m_sContextOrJob ) == 0 ) + { + //log this assert + { + // !FIXME! DOTAMERGE + //CGCInterface::CDisableAssertRateLimit disableAssertLimit; + + // !FIXME! DOTAMERGE + // AssertMsg varargs + AssertMsg3( false, "GCSystemAccess Caught %s (context %s) calling into %s", pszJobName, pContext->GetName(), pSystem ? pSystem->m_sName.String() : "unknown" ); + } + + //and clear it + delete pAssert; + m_SingleAsserts.FastRemove( nCurrAssert ); + } + } + } + + //at this point, if it is a valid access, just bail + if( bValidAccess ) + return true; + + //otherwise, handle the failure case + if( nActions & ( GCAccessAction_Msg | GCAccessAction_Assert ) ) + { + int nSystemIndex = m_Systems.Find( nSystem ); + const char* pszSystem = ( nSystemIndex != m_Systems.InvalidIndex() ) ? m_Systems[ nSystemIndex ]->m_sName.String() : "<unregistered>"; + + //display a message based upon if it was a system or ID violation + CFmtStr1024 szMsg; + if( !bValidSystem ) + { + szMsg.sprintf( "Job %s Accessed invalid system %s (%u) while in context %s\n", pszJobName, pszSystem, nSystem, pContext->GetName() ); + } + else + { + szMsg.sprintf( "Job %s Accessed invalid steam ID %s but expected %s in system %s (%u) while in context %s\n", pszJobName, steamID.RenderLink(), expectedID.RenderLink(), pszSystem, nSystem, pContext->GetName() ); + } + + if( nActions & GCAccessAction_Msg ) + EG_MSG( g_EGAccess, "%s", szMsg.String() ); + if( nActions & GCAccessAction_Assert ) + { + // !FIXME! DOTAMERGE + // AssertMsg varargs + AssertMsg1( false, "%s", szMsg.String() ); + } + } + + return !( nActions & GCAccessAction_ReturnFail ); +} + +void CGCAccess::SuppressAccess( GCAccessSystem_t nSystem, bool bEnable ) +{ + //see if it is an existing item already suppressed that we need to modify the ref count of + FOR_EACH_VEC( m_SuppressAccess, nAccess ) + { + if( m_SuppressAccess[ nAccess ].m_nSystem == nSystem ) + { + if( bEnable ) + { + //to enable, we want to decrease the disable count, or remove if we are fully re-enabled + if( m_SuppressAccess[ nAccess ].m_nCount <= 1 ) + m_SuppressAccess.FastRemove( nAccess ); + else + m_SuppressAccess[ nAccess ].m_nCount--; + } + else + { + m_SuppressAccess[ nAccess ].m_nCount++; + } + return; + } + } + + //only add it to the list if we are disabling + if( !bEnable ) + { + SuppressAccess_t access; + access.m_nSystem = nSystem; + access.m_nCount = 1; + m_SuppressAccess.AddToTail( access ); + } +} + +void CGCAccess::ClearSystemStats() +{ + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + m_Systems[ nSystem ]->m_Jobs.Purge(); + } +} + +bool CGCAccess::CatchSingleAssert( const char* pszSystem, bool bContext, const char* pszContextOrJob ) +{ + //find the system we are referencing so we don't add invalid breakpoints if we can avoid it + GCAccessSystem_t nSystemID = ( GCAccessSystem_t )-1; + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + if( V_stricmp( m_Systems[ nSystem ]->m_sName, pszSystem ) == 0 ) + { + nSystemID = m_Systems.Key( nSystem ); + break; + } + } + + if( nSystemID == ( GCAccessSystem_t )-1 ) + return false; + + SingleAssert_t* pAssert = new SingleAssert_t; + pAssert->m_System = nSystemID; + pAssert->m_bContext = bContext; + pAssert->m_sContextOrJob = pszContextOrJob; + m_SingleAsserts.AddToTail( pAssert ); + return true; +} + +void CGCAccess::ClearSingleAsserts() +{ + m_SingleAsserts.PurgeAndDeleteElements(); +} + + +//given a display type and a stats object, determines if it meets the criteria +static bool ShouldDisplayStats( CGCAccess::EDisplay eDisplay, const CGCAccessSystem::AccessStats_t& stats ) +{ + if( eDisplay == CGCAccess::eDisplay_Referenced ) + return ( stats.m_nNumFail + stats.m_nNumFailID + stats.m_nNumValid ) > 0; + if( eDisplay == CGCAccess::eDisplay_Violations ) + return ( stats.m_nNumFail + stats.m_nNumFailID ) > 0; + if( eDisplay == CGCAccess::eDisplay_IDViolations ) + return stats.m_nNumFailID > 0; + + //unknown, so just assume all + return true; +} + + +void CGCAccess::ReportJobs( const char* pszContext, EDisplay eDisplay ) const +{ + //collect all of the job stats into a single summary table + CUtlHashMapLarge< uintp, CGCAccessSystem::TrackedJob_t > jobs; + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + const CGCAccessSystem* pSystem = m_Systems[ nSystem ]; + FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob ) + { + const CGCAccessSystem::TrackedJob_t& job = pSystem->m_Jobs[ nJob ]; + //skip any contexts we don't care about + if( pszContext && ( V_stricmp( pszContext, job.m_sContext ) != 0 ) ) + continue; + if( !ShouldDisplayStats( eDisplay, job.m_Stats ) ) + continue; + + int nIndex = jobs.Find( pSystem->m_Jobs.Key( nJob ) ); + if( nIndex == jobs.InvalidIndex() ) + { + nIndex = jobs.Insert( pSystem->m_Jobs.Key( nJob ) ); + jobs[ nIndex ].m_sContext = job.m_sContext; + } + + jobs[ nIndex ].m_Stats.Add( job.m_Stats ); + } + } + + CGCReportPrinter rp; + rp.AddStringColumn( "Job" ); + rp.AddStringColumn( "Context" ); + rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total ); + + FOR_EACH_MAP_FAST( jobs, nJob ) + { + rp.StrValue( ( const char* )jobs.Key( nJob ), CFmtStr( "gcaccess_dump_job \"%s\" %d", ( const char* )jobs.Key( nJob ), eDisplay ).String() ); + rp.StrValue( jobs[ nJob ].m_sContext, CFmtStr( "gcaccess_dump_context \"%s\" %d", jobs[ nJob ].m_sContext.String(), eDisplay ).String() ); + rp.IntValue( jobs[ nJob ].m_Stats.m_nNumValid ); + rp.IntValue( jobs[ nJob ].m_Stats.m_nNumFail ); + rp.IntValue( jobs[ nJob ].m_Stats.m_nNumFailID ); + rp.CommitRow(); + } + + rp.SortReport( "Job", false ); + rp.PrintReport( SPEW_CONSOLE ); +} + +void CGCAccess::ReportSystems( const char* pszContext, EDisplay eDisplay ) const +{ + CGCReportPrinter rp; + rp.AddStringColumn( "System" ); + rp.AddIntColumn( "ID", CGCReportPrinter::eSummary_None ); + rp.AddIntColumn( "Jobs", CGCReportPrinter::eSummary_None ); + rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total ); + + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + const CGCAccessSystem* pSystem = m_Systems[ nSystem ]; + CGCAccessSystem::AccessStats_t stats; + FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob ) + { + const CGCAccessSystem::TrackedJob_t& job = pSystem->m_Jobs[ nJob ]; + //skip any contexts we don't care about + if( pszContext && ( V_stricmp( pszContext, job.m_sContext ) != 0 ) ) + continue; + + stats.Add( job.m_Stats ); + } + + if( !ShouldDisplayStats( eDisplay, stats ) ) + continue; + + rp.StrValue( pSystem->m_sName, CFmtStr( "gcaccess_dump_system \"%s\" %d", pSystem->m_sName.String(), eDisplay ).String() ); + rp.IntValue( pSystem->m_nID ); + rp.IntValue( pSystem->m_Jobs.Count() ); + rp.IntValue( stats.m_nNumValid ); + rp.IntValue( stats.m_nNumFail ); + rp.IntValue( stats.m_nNumFailID ); + rp.CommitRow(); + } + + rp.SortReport( "System", false ); + rp.PrintReport( SPEW_CONSOLE ); +} + +void CGCAccess::FullReport( const char* pszSystemFilter, const char* pszContextFilter, const char* pszJobFilter, EDisplay eDisplay ) const +{ + CGCReportPrinter rp; + rp.AddStringColumn( "Job" ); + rp.AddStringColumn( "Context" ); + rp.AddStringColumn( "System" ); + rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total ); + + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + const CGCAccessSystem* pSystem = m_Systems[ nSystem ]; + if( pszSystemFilter && V_stricmp( pszSystemFilter, pSystem->m_sName ) ) + continue; + + FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob ) + { + const CGCAccessSystem::AccessStats_t& stats = pSystem->m_Jobs[ nJob ].m_Stats; + const char* pszJob = ( const char* )pSystem->m_Jobs.Key( nJob ); + const char* pszContext = ( const char* )pSystem->m_Jobs[ nJob ].m_sContext; + + if( !ShouldDisplayStats( eDisplay, stats ) ) + continue; + if( pszJobFilter && V_stricmp( pszJobFilter, pszJob ) ) + continue; + if( pszContextFilter && V_stricmp( pszContextFilter, pszContext ) ) + continue; + + rp.StrValue( pszJob, CFmtStr( "gcaccess_dump_job \"%s\" %d", pszJob, eDisplay ).String() ); + rp.StrValue( pszContext, CFmtStr( "gcaccess_dump_context \"%s\" %d", pszContext, eDisplay ).String() ); + rp.StrValue( pSystem->m_sName, CFmtStr( "gcaccess_dump_system \"%s\" %d", pSystem->m_sName.String(), eDisplay ).String() ); + rp.IntValue( stats.m_nNumValid ); + rp.IntValue( stats.m_nNumFail ); + rp.IntValue( stats.m_nNumFailID ); + rp.CommitRow(); + } + } + + rp.SortReport( "Context", false ); + rp.PrintReport( SPEW_CONSOLE ); +} + +void CGCAccess::DependencyReport( const char* pszSystem, EDisplay eDisplay ) const +{ + //first off, we need to find the system we are scanning for dependencies on + const CGCAccessSystem* pMatchSystem = NULL; + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + const CGCAccessSystem* pSystem = m_Systems[ nSystem ]; + if( V_stricmp( pszSystem, pSystem->m_sName ) == 0 ) + { + pMatchSystem = pSystem; + break; + } + } + + if( !pMatchSystem ) + { + EG_MSG( SPEW_CONSOLE, "Unable to find system %s for dependency report\n", pszSystem ); + return; + } + + //now generate our report + CGCReportPrinter rp; + rp.AddStringColumn( "Job" ); + rp.AddStringColumn( "Context" ); + rp.AddStringColumn( "System" ); + rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total ); + rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total ); + + FOR_EACH_MAP_FAST( m_Systems, nSystem ) + { + const CGCAccessSystem* pSystem = m_Systems[ nSystem ]; + //skip ourself + if( pSystem == pMatchSystem ) + continue; + + FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob ) + { + const CGCAccessSystem::AccessStats_t& stats = pSystem->m_Jobs[ nJob ].m_Stats; + const char* pszJob = ( const char* )pSystem->m_Jobs.Key( nJob ); + const char* pszContext = ( const char* )pSystem->m_Jobs[ nJob ].m_sContext; + + //skip any job that isn't using our match system + if( !pMatchSystem->m_Jobs.HasElement( ( uintp )pszJob ) ) + continue; + if( !ShouldDisplayStats( eDisplay, stats ) ) + continue; + + rp.StrValue( pszJob, CFmtStr( "gcaccess_dump_job \"%s\" %d", pszJob, eDisplay ).String() ); + rp.StrValue( pszContext, CFmtStr( "gcaccess_dump_context \"%s\" %d", pszContext, eDisplay ).String() ); + rp.StrValue( pSystem->m_sName, CFmtStr( "gcaccess_dump_system \"%s\" %d", pSystem->m_sName.String(), eDisplay ).String() ); + rp.IntValue( stats.m_nNumValid ); + rp.IntValue( stats.m_nNumFail ); + rp.IntValue( stats.m_nNumFailID ); + rp.CommitRow(); + } + } + + rp.SortReport( "System", false ); + rp.PrintReport( SPEW_CONSOLE ); + + +} + +GC_CON_COMMAND_PARAMS( gcaccess_dump_job, 1, "<Job Name> Dumps all of the accesses associated with the specified job" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().FullReport( NULL, NULL, args[ 1 ], eDisplay ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_dump_context, 1, "<Job Name> Dumps all of the accesses associated with the specified context" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().FullReport( NULL, args[ 1 ], NULL, eDisplay ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_dump_system, 1, "<Job Name> Dumps all of the accesses associated with the specified system" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().FullReport( args[ 1 ], NULL, NULL, eDisplay ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_dump_context_jobs, 1, "<Context Name> Dumps all of the accesses associated with the specified context" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().ReportJobs( args[ 1 ], eDisplay ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_dump_context_systems, 1, "<Context Name> Dumps all of the accesses associated with the specified context" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().ReportSystems( args[ 1 ], eDisplay ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_dump_system_dependencies, 1, "<System Name> This will dump out for all jobs that reference the specified system, what other systems they reference" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().DependencyReport( args[ 1 ], eDisplay ); +} + +GC_CON_COMMAND( gcaccess_dump_jobs, "Dumps all the jobs that have been tracked with the gcaccess system as well as count of violations" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 2 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 1 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().ReportJobs( NULL, eDisplay); +} + +GC_CON_COMMAND( gcaccess_dump_systems, "Dumps all the systems that have been tracked with the gcaccess system as well as count of violations" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 2 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 1 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().ReportSystems( NULL, eDisplay ); +} + +GC_CON_COMMAND( gcaccess_dump_full, "Dumps all the information tracked by the gcaccess" ) +{ + CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 2 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 1 ] ) : CGCAccess::eDisplay_Referenced; + GGCAccess().FullReport( NULL, NULL, NULL, eDisplay ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_catch_context, 2, "<system> <context> - Catches and generates an assert when the specified context calls into the provided system. This will only generate a single assert" ) +{ + if( !GGCAccess().CatchSingleAssert( args[ 1 ], true, args[ 2 ] ) ) + EG_MSG( SPEW_CONSOLE, "Unable to register catch, likely \'%s\' is not a valid system.", args[ 1 ] ); +} + +GC_CON_COMMAND_PARAMS( gcaccess_catch_job, 2, "<system> <job> - Catches and generates an assert when the specified job calls into the provided system. This will only generate a single assert" ) +{ + if( !GGCAccess().CatchSingleAssert( args[ 1 ], false, args[ 2 ] ) ) + EG_MSG( SPEW_CONSOLE, "Unable to register catch, likely \'%s\' is not a valid system.", args[ 1 ] ); +} + +GC_CON_COMMAND( gcaccess_catch_clear, "Clears all previously specified catches" ) +{ + GGCAccess().ClearSingleAsserts(); +} + +} //namespace GCSDK |