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.
195 lines
5.2 KiB
195 lines
5.2 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
//=======================================================================================//
|
||
|
|
||
|
#include "baserecordingsession.h"
|
||
|
#include "baserecordingsessionblock.h"
|
||
|
#include "replay/irecordingsessionblockmanager.h"
|
||
|
#include "replay/replayutils.h"
|
||
|
#include "replay/iclientreplaycontext.h"
|
||
|
#include "replay/shared_defs.h"
|
||
|
#include "KeyValues.h"
|
||
|
#include "replay/replayutils.h"
|
||
|
#include "replay/ireplaycontext.h"
|
||
|
#include "filesystem.h"
|
||
|
#include "iserver.h"
|
||
|
#include "replaysystem.h"
|
||
|
#include "utlbuffer.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|
||
|
|
||
|
CBaseRecordingSession::CBaseRecordingSession( IReplayContext *pContext )
|
||
|
: m_pContext( pContext ),
|
||
|
m_bRecording( false ),
|
||
|
m_bAutoDelete( false ),
|
||
|
m_bBlocksLoaded( false ),
|
||
|
m_flStartTime( 0.0f )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CBaseRecordingSession::~CBaseRecordingSession()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::AddBlock( CBaseRecordingSessionBlock *pBlock )
|
||
|
{
|
||
|
AddBlock( pBlock, false );
|
||
|
}
|
||
|
|
||
|
bool CBaseRecordingSession::Read( KeyValues *pIn )
|
||
|
{
|
||
|
if ( !BaseClass::Read( pIn ) )
|
||
|
return false;
|
||
|
|
||
|
m_strName = pIn->GetString( "name" );
|
||
|
|
||
|
if ( m_strName.IsEmpty() )
|
||
|
{
|
||
|
CUtlBuffer buf;
|
||
|
pIn->RecursiveSaveToFile( buf, 0 );
|
||
|
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() ) );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
m_bRecording = pIn->GetBool( "recording" );
|
||
|
m_strBaseDownloadURL = pIn->GetString( "base_download_url" );
|
||
|
m_nServerStartRecordTick = pIn->GetInt( "server_start_record_tick", -1 );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::Write( KeyValues *pOut )
|
||
|
{
|
||
|
BaseClass::Write( pOut );
|
||
|
|
||
|
pOut->SetString( "name", m_strName.Get() );
|
||
|
pOut->SetInt( "recording", m_bRecording ? 1 : 0 );
|
||
|
pOut->SetString( "base_download_url", m_strBaseDownloadURL.Get() );
|
||
|
pOut->SetInt( "server_start_record_tick", m_nServerStartRecordTick );
|
||
|
}
|
||
|
|
||
|
const char *CBaseRecordingSession::GetSubKeyTitle() const
|
||
|
{
|
||
|
return m_strName.Get();
|
||
|
}
|
||
|
|
||
|
const char *CBaseRecordingSession::GetPath() const
|
||
|
{
|
||
|
return Replay_va( "%s%s%c", m_pContext->GetBaseDir(), SUBDIR_SESSIONS, CORRECT_PATH_SEPARATOR );
|
||
|
}
|
||
|
|
||
|
const char *CBaseRecordingSession::GetSessionInfoURL() const
|
||
|
{
|
||
|
return Replay_va( "%s%s.%s", m_strBaseDownloadURL.Get(), m_strName.Get(), GENERIC_FILE_EXTENSION );
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::LoadBlocksForSession()
|
||
|
{
|
||
|
if ( m_bBlocksLoaded )
|
||
|
return;
|
||
|
|
||
|
IRecordingSessionBlockManager *pBlockManager = m_pContext->GetRecordingSessionBlockManager();
|
||
|
|
||
|
// Peek in directory and load files based on what's there
|
||
|
FileFindHandle_t hFind;
|
||
|
CFmtStr fmtPath( "%s%s*.%s", pBlockManager->GetBlockPath(), m_strName.Get(), GENERIC_FILE_EXTENSION );
|
||
|
const char *pFilename = g_pFullFileSystem->FindFirst( fmtPath.Access(), &hFind );
|
||
|
while ( pFilename )
|
||
|
{
|
||
|
// Load the block - this will add the block to this session
|
||
|
pBlockManager->LoadBlockFromFileName( pFilename, this );
|
||
|
|
||
|
// Get next file
|
||
|
pFilename = g_pFullFileSystem->FindNext( hFind );
|
||
|
}
|
||
|
|
||
|
// Blocks loaded
|
||
|
m_bBlocksLoaded = true;
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::OnDelete()
|
||
|
{
|
||
|
BaseClass::OnDelete();
|
||
|
|
||
|
// Dynamically load blocks if necessary, then delete from the block manager and from disk
|
||
|
DeleteBlocks();
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::DeleteBlocks()
|
||
|
{
|
||
|
if ( !m_bBlocksLoaded )
|
||
|
{
|
||
|
// Load blocks now based on the session name
|
||
|
LoadBlocksForSession();
|
||
|
}
|
||
|
|
||
|
// Delete all blocks associated w/ the session
|
||
|
FOR_EACH_VEC( m_vecBlocks, i )
|
||
|
{
|
||
|
CBaseRecordingSessionBlock *pCurBlock = m_vecBlocks[ i ];
|
||
|
m_pContext->GetRecordingSessionBlockManager()->DeleteBlock( pCurBlock );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::OnUnload()
|
||
|
{
|
||
|
BaseClass::OnUnload();
|
||
|
|
||
|
FOR_EACH_VEC( m_vecBlocks, i )
|
||
|
{
|
||
|
CBaseRecordingSessionBlock *pCurBlock = m_vecBlocks[ i ];
|
||
|
m_pContext->GetRecordingSessionBlockManager()->UnloadBlock( pCurBlock );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::PopulateWithRecordingData( int nCurrentRecordingStartTick )
|
||
|
{
|
||
|
Assert( nCurrentRecordingStartTick >= 0 );
|
||
|
|
||
|
m_strBaseDownloadURL = Replay_GetDownloadURL();
|
||
|
m_bRecording = true;
|
||
|
m_nServerStartRecordTick = nCurrentRecordingStartTick;
|
||
|
}
|
||
|
|
||
|
void CBaseRecordingSession::AddBlock( CBaseRecordingSessionBlock *pBlock, bool bFlagForFlush )
|
||
|
{
|
||
|
Assert( pBlock->m_hSession == GetHandle() );
|
||
|
|
||
|
Assert( m_vecBlocks.Find( pBlock ) == m_vecBlocks.InvalidIndex() );
|
||
|
m_vecBlocks.Insert( pBlock );
|
||
|
|
||
|
if ( bFlagForFlush )
|
||
|
{
|
||
|
// Mark as dirty
|
||
|
m_pContext->GetRecordingSessionManager()->FlagSessionForFlush( this, false );
|
||
|
}
|
||
|
|
||
|
m_bBlocksLoaded = true;
|
||
|
}
|
||
|
|
||
|
int CBaseRecordingSession::FindBlock( CBaseRecordingSessionBlock *pBlock ) const
|
||
|
{
|
||
|
int itResult = m_vecBlocks.Find( pBlock );
|
||
|
if ( itResult == m_vecBlocks.InvalidIndex() )
|
||
|
return -1;
|
||
|
|
||
|
return itResult;
|
||
|
}
|
||
|
|
||
|
bool CBaseRecordingSession::ShouldDitchSession() const
|
||
|
{
|
||
|
return m_bAutoDelete;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|
||
|
|
||
|
bool CBaseRecordingSession::CLessFunctor::Less( const CBaseRecordingSessionBlock *pSrc1, const CBaseRecordingSessionBlock *pSrc2, void *pContext )
|
||
|
{
|
||
|
return pSrc1->m_iReconstruction < pSrc2->m_iReconstruction;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|