Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
5.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //=======================================================================================//
  4. #include "baserecordingsession.h"
  5. #include "baserecordingsessionblock.h"
  6. #include "replay/irecordingsessionblockmanager.h"
  7. #include "replay/replayutils.h"
  8. #include "replay/iclientreplaycontext.h"
  9. #include "replay/shared_defs.h"
  10. #include "KeyValues.h"
  11. #include "replay/replayutils.h"
  12. #include "replay/ireplaycontext.h"
  13. #include "filesystem.h"
  14. #include "iserver.h"
  15. #include "replaysystem.h"
  16. #include "utlbuffer.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. //----------------------------------------------------------------------------------------
  20. CBaseRecordingSession::CBaseRecordingSession( IReplayContext *pContext )
  21. : m_pContext( pContext ),
  22. m_bRecording( false ),
  23. m_bAutoDelete( false ),
  24. m_bBlocksLoaded( false ),
  25. m_flStartTime( 0.0f )
  26. {
  27. }
  28. CBaseRecordingSession::~CBaseRecordingSession()
  29. {
  30. }
  31. void CBaseRecordingSession::AddBlock( CBaseRecordingSessionBlock *pBlock )
  32. {
  33. AddBlock( pBlock, false );
  34. }
  35. bool CBaseRecordingSession::Read( KeyValues *pIn )
  36. {
  37. if ( !BaseClass::Read( pIn ) )
  38. return false;
  39. m_strName = pIn->GetString( "name" );
  40. if ( m_strName.IsEmpty() )
  41. {
  42. CUtlBuffer buf;
  43. pIn->RecursiveSaveToFile( buf, 0 );
  44. IF_REPLAY_DBG( Warning( "Session with no session name found - aborting load for this session. Data:\n---\n%s\n---\n", (const char *)buf.Base() ) );
  45. return false;
  46. }
  47. m_bRecording = pIn->GetBool( "recording" );
  48. m_strBaseDownloadURL = pIn->GetString( "base_download_url" );
  49. m_nServerStartRecordTick = pIn->GetInt( "server_start_record_tick", -1 );
  50. return true;
  51. }
  52. void CBaseRecordingSession::Write( KeyValues *pOut )
  53. {
  54. BaseClass::Write( pOut );
  55. pOut->SetString( "name", m_strName.Get() );
  56. pOut->SetInt( "recording", m_bRecording ? 1 : 0 );
  57. pOut->SetString( "base_download_url", m_strBaseDownloadURL.Get() );
  58. pOut->SetInt( "server_start_record_tick", m_nServerStartRecordTick );
  59. }
  60. const char *CBaseRecordingSession::GetSubKeyTitle() const
  61. {
  62. return m_strName.Get();
  63. }
  64. const char *CBaseRecordingSession::GetPath() const
  65. {
  66. return Replay_va( "%s%s%c", m_pContext->GetBaseDir(), SUBDIR_SESSIONS, CORRECT_PATH_SEPARATOR );
  67. }
  68. const char *CBaseRecordingSession::GetSessionInfoURL() const
  69. {
  70. return Replay_va( "%s%s.%s", m_strBaseDownloadURL.Get(), m_strName.Get(), GENERIC_FILE_EXTENSION );
  71. }
  72. void CBaseRecordingSession::LoadBlocksForSession()
  73. {
  74. if ( m_bBlocksLoaded )
  75. return;
  76. IRecordingSessionBlockManager *pBlockManager = m_pContext->GetRecordingSessionBlockManager();
  77. // Peek in directory and load files based on what's there
  78. FileFindHandle_t hFind;
  79. CFmtStr fmtPath( "%s%s*.%s", pBlockManager->GetBlockPath(), m_strName.Get(), GENERIC_FILE_EXTENSION );
  80. const char *pFilename = g_pFullFileSystem->FindFirst( fmtPath.Access(), &hFind );
  81. while ( pFilename )
  82. {
  83. // Load the block - this will add the block to this session
  84. pBlockManager->LoadBlockFromFileName( pFilename, this );
  85. // Get next file
  86. pFilename = g_pFullFileSystem->FindNext( hFind );
  87. }
  88. // Blocks loaded
  89. m_bBlocksLoaded = true;
  90. }
  91. void CBaseRecordingSession::OnDelete()
  92. {
  93. BaseClass::OnDelete();
  94. // Dynamically load blocks if necessary, then delete from the block manager and from disk
  95. DeleteBlocks();
  96. }
  97. void CBaseRecordingSession::DeleteBlocks()
  98. {
  99. if ( !m_bBlocksLoaded )
  100. {
  101. // Load blocks now based on the session name
  102. LoadBlocksForSession();
  103. }
  104. // Delete all blocks associated w/ the session
  105. FOR_EACH_VEC( m_vecBlocks, i )
  106. {
  107. CBaseRecordingSessionBlock *pCurBlock = m_vecBlocks[ i ];
  108. m_pContext->GetRecordingSessionBlockManager()->DeleteBlock( pCurBlock );
  109. }
  110. }
  111. void CBaseRecordingSession::OnUnload()
  112. {
  113. BaseClass::OnUnload();
  114. FOR_EACH_VEC( m_vecBlocks, i )
  115. {
  116. CBaseRecordingSessionBlock *pCurBlock = m_vecBlocks[ i ];
  117. m_pContext->GetRecordingSessionBlockManager()->UnloadBlock( pCurBlock );
  118. }
  119. }
  120. void CBaseRecordingSession::PopulateWithRecordingData( int nCurrentRecordingStartTick )
  121. {
  122. Assert( nCurrentRecordingStartTick >= 0 );
  123. m_strBaseDownloadURL = Replay_GetDownloadURL();
  124. m_bRecording = true;
  125. m_nServerStartRecordTick = nCurrentRecordingStartTick;
  126. }
  127. void CBaseRecordingSession::AddBlock( CBaseRecordingSessionBlock *pBlock, bool bFlagForFlush )
  128. {
  129. Assert( pBlock->m_hSession == GetHandle() );
  130. Assert( m_vecBlocks.Find( pBlock ) == m_vecBlocks.InvalidIndex() );
  131. m_vecBlocks.Insert( pBlock );
  132. if ( bFlagForFlush )
  133. {
  134. // Mark as dirty
  135. m_pContext->GetRecordingSessionManager()->FlagSessionForFlush( this, false );
  136. }
  137. m_bBlocksLoaded = true;
  138. }
  139. int CBaseRecordingSession::FindBlock( CBaseRecordingSessionBlock *pBlock ) const
  140. {
  141. int itResult = m_vecBlocks.Find( pBlock );
  142. if ( itResult == m_vecBlocks.InvalidIndex() )
  143. return -1;
  144. return itResult;
  145. }
  146. bool CBaseRecordingSession::ShouldDitchSession() const
  147. {
  148. return m_bAutoDelete;
  149. }
  150. //----------------------------------------------------------------------------------------
  151. bool CBaseRecordingSession::CLessFunctor::Less( const CBaseRecordingSessionBlock *pSrc1, const CBaseRecordingSessionBlock *pSrc2, void *pContext )
  152. {
  153. return pSrc1->m_iReconstruction < pSrc2->m_iReconstruction;
  154. }
  155. //----------------------------------------------------------------------------------------