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.
|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "sv_fileservercleanup.h"
#include "sv_replaycontext.h"
#include "sv_recordingsession.h"
#include "spew.h"
#if BUILD_CURL
#include "curl/curl.h"
#endif
#undef AddJob
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//----------------------------------------------------------------------------------------
#if _DEBUG
ConVar replay_fileserver_simulate_delete( "replay_fileserver_simulate_delete", "0", FCVAR_GAMEDLL, "Don't delete any actual files during replay cleanup." ); #endif
//----------------------------------------------------------------------------------------
IFileserverCleanerJob *SV_CastJobToIFileserverCleanerJob( CBaseJob *pJob ) { IFileserverCleanerJob *pResult = dynamic_cast< IFileserverCleanerJob * >( pJob ); AssertMsg( pResult != NULL, "Cast failed! Are you sure this job is an IFileserverCleanerJob?" ); return pResult; }
//----------------------------------------------------------------------------------------
CFileserverCleaner::CFileserverCleaner() : m_bRunning( false ), m_bPrintResult( false ), m_pCleanerJob( NULL ), m_pSpewer( NULL ), m_nNumFilesDeleted( 0 ) { }
void CFileserverCleaner::MarkFileForDelete( const char *pFilename ) { if ( m_bRunning ) return;
// Create cleaner job now if need be
if ( !m_pCleanerJob ) { m_pCleanerJob = SV_CreateDeleteFileJob(); m_nNumFilesDeleted = 0; }
IFileserverCleanerJob *pCleanerJobImp = SV_CastJobToIFileserverCleanerJob( m_pCleanerJob ); AssertMsg( pCleanerJobImp != NULL, "This cast should always work!" ); if ( pCleanerJobImp ) { pCleanerJobImp->AddFileForDelete( pFilename ); } }
void CFileserverCleaner::BlockForCompletion() { if ( !m_bRunning ) return;
if ( !m_pCleanerJob ) return;
m_pCleanerJob->WaitForFinish();
Clear(); }
void CFileserverCleaner::DoCleanAsynchronous( bool bPrintResult/*=false*/, ISpewer *pSpewer/*=g_pDefaultSpewer*/ ) { if ( m_bRunning ) return;
if ( !m_pCleanerJob ) return;
m_pSpewer = pSpewer; m_bPrintResult = bPrintResult; m_bRunning = true;
SV_GetThreadPool()->AddJob( m_pCleanerJob ); }
void CFileserverCleaner::Clear() { m_pCleanerJob->Release(); m_pCleanerJob = NULL;
m_bPrintResult = false; m_bRunning = false; }
void CFileserverCleaner::Think() { CBaseThinker::Think();
if ( !m_bRunning ) return;
if ( !m_pCleanerJob->IsFinished() ) return;
IFileserverCleanerJob *pCleanerJobImp = SV_CastJobToIFileserverCleanerJob( m_pCleanerJob ); if ( pCleanerJobImp ) { m_nNumFilesDeleted += pCleanerJobImp->GetNumFilesDeleted(); }
PrintResult(); Clear(); }
void CFileserverCleaner::PrintResult() { if ( !m_bPrintResult || !m_pSpewer ) return;
m_pSpewer->PrintEmptyLine();
const int nNumFilesRemoved = SV_GetFileserverCleaner()->GetNumFilesDeleted(); m_pSpewer->PrintValue( "Number of files removed", Replay_va( "%i", nNumFilesRemoved ) );
m_pSpewer->PrintBlockEnd(); }
float CFileserverCleaner::GetNextThinkTime() const { return 0.0f; }
//----------------------------------------------------------------------------------------
CLocalFileDeleterJob::CLocalFileDeleterJob() : m_nNumDeleted( 0 ) { }
void CLocalFileDeleterJob::AddFileForDelete( const char *pFilename ) { CFmtStr fmtFullFilename( "%s%s", g_pServerReplayContext->GetLocalFileServerPath(), pFilename ); m_vecFiles.CopyAndAddToTail( fmtFullFilename.Access() ); }
JobStatus_t CLocalFileDeleterJob::DoExecute() { bool bResult = true;
FOR_EACH_VEC( m_vecFiles, i ) { const char *pCurFilename = m_vecFiles[ i ];
// File exists?
PrintEventStartMsg( "File exists?" ); if ( !g_pFullFileSystem->FileExists( pCurFilename ) ) { CFmtStr fmtError( "File '%s' does not exist", pCurFilename ); SetError( ERROR_FILE_DOES_NOT_EXIST, fmtError.Access() ); // TODO: This will only catch the last filename
PrintEventResult( false ); bResult = false; continue; } PrintEventResult( true );
// Delete the file
PrintEventStartMsg( "Deleting file" ); g_pFullFileSystem->RemoveFile( pCurFilename );
// File gone?
const bool bDeleted = !g_pFullFileSystem->FileExists( pCurFilename ); PrintEventResult( bDeleted );
// Increment # deleted if appropriate
if ( bDeleted ) { ++m_nNumDeleted; }
bResult = bResult && bDeleted; }
return bResult ? JOB_OK : JOB_FAILED; }
//----------------------------------------------------------------------------------------
CLocalFileDeleterJob *SV_CreateLocalFileDeleterJob() { return new CLocalFileDeleterJob(); }
//----------------------------------------------------------------------------------------
bool SV_DoFileserverCleanup( bool bForceCleanAll, ISpewer *pSpewer ) { CServerRecordingSessionManager *pSessionManager = SV_GetRecordingSessionManager(); CBaseRecordingSession *pRecordingSession = SV_GetRecordingSessionInProgress();
for ( int i = 0; i < pSessionManager->Count(); ) { CServerRecordingSession *pCurSession = SV_CastSession( SV_GetRecordingSessionManager()->m_vecObjs[ i ] );
// Skip session in progress
bool bRemoved = false; if ( pCurSession != NULL && pCurSession != pRecordingSession ) { // Session expired?
if ( bForceCleanAll || pCurSession->SessionExpired() ) { // The session's OnDelete() will add the session file to the cleanup system,
// and also delete all associated blocks, whose OnDelete() will also add their
// associated .block files to the cleanup system.
pSessionManager->RemoveFromIndex( i );
bRemoved = true; } }
if ( !bRemoved ) { ++i; } }
pSpewer->PrintBlockStart();
pSpewer->PrintMsg( "Attempting to clean up stale replay data..." ); pSpewer->PrintEmptyLine();
// NOTE: There may be files queued up in addition to those marked above
if ( !SV_GetFileserverCleaner()->HasFilesQueuedForDelete() ) { pSpewer->PrintMsg( "No replay data to clean up." ); pSpewer->PrintBlockEnd(); } else { // Asynchronously delete all collected files
SV_GetFileserverCleaner()->DoCleanAsynchronous( true, g_pBlockSpewer ); }
return true; }
CBaseJob *SV_CreateDeleteFileJob() { return SV_CreateLocalFileDeleterJob(); }
//----------------------------------------------------------------------------------------
|