diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /replay/sv_fileservercleanup.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'replay/sv_fileservercleanup.cpp')
| -rw-r--r-- | replay/sv_fileservercleanup.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/replay/sv_fileservercleanup.cpp b/replay/sv_fileservercleanup.cpp new file mode 100644 index 0000000..c3ac061 --- /dev/null +++ b/replay/sv_fileservercleanup.cpp @@ -0,0 +1,260 @@ +//========= 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(); +} + +//---------------------------------------------------------------------------------------- |