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.
545 lines
20 KiB
545 lines
20 KiB
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Manager for handling UGC file requests
|
|
//
|
|
//========================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "ugc_request_manager.h"
|
|
|
|
#if !defined(NO_STEAM) && !defined(_PS3)
|
|
|
|
static uint64 g_TimeStampIncr = 0;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// LessFunc for UGC operation (priority / timestamp)
|
|
//-----------------------------------------------------------------------------
|
|
bool UGCOperationsLessFunc( UGCFileRequest_t * const &lhs, UGCFileRequest_t * const &rhs )
|
|
{
|
|
// If the priorities are equal, then we tie-break on the time they were submitted (rhs wins if another tie occurs)
|
|
if ( lhs->GetPriority() == rhs->GetPriority() )
|
|
return ( lhs->GetTimestamp() >= rhs->GetTimestamp() );
|
|
|
|
return ( lhs->GetPriority() < rhs->GetPriority() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CUGCFileRequestManager::CUGCFileRequestManager( void )
|
|
{
|
|
m_PendingFileOperations.SetLessFunc( UGCOperationsLessFunc );
|
|
m_FileRequests.SetLessFunc( DefLessFunc( UGCHandle_t ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CUGCFileRequestManager::DeleteFileRequest( UGCHandle_t handle, bool bRemoveFromDisk /*= false*/ )
|
|
{
|
|
if ( handle == k_UGCHandleInvalid )
|
|
return false;
|
|
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( handle );
|
|
if ( pRequest == NULL )
|
|
return false;
|
|
|
|
// Clear it from our pending work
|
|
for ( int i=0; i < m_PendingFileOperations.Count(); i++ )
|
|
{
|
|
UGCFileRequest_t *pQueueRequest = m_PendingFileOperations.Element( i );
|
|
if ( pQueueRequest && pQueueRequest->fileHandle == handle )
|
|
{
|
|
m_PendingFileOperations.RemoveAt( i );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Remove it from our library
|
|
if ( m_FileRequests.Remove( handle ) == false )
|
|
return false;
|
|
|
|
// Clean it off disk as well
|
|
if ( bRemoveFromDisk )
|
|
{
|
|
|
|
char szLocalFilename[MAX_PATH];
|
|
pRequest->fileRequest.GetFullPath( szLocalFilename, sizeof(szLocalFilename) );
|
|
g_pFullFileSystem->RemoveFile( szLocalFilename );
|
|
}
|
|
|
|
delete pRequest;
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CUGCFileRequestManager::Update( void )
|
|
{
|
|
while ( m_PendingFileOperations.Count() )
|
|
{
|
|
UGCFileRequest_t *pFileRequest = m_PendingFileOperations.ElementAtHead();
|
|
|
|
Assert( pFileRequest != NULL );
|
|
if ( pFileRequest == NULL )
|
|
{
|
|
// FIXME: Throw a warning
|
|
m_PendingFileOperations.RemoveAtHead();
|
|
continue;
|
|
}
|
|
|
|
UGCFileRequestStatus_t ugcStatus = pFileRequest->fileRequest.Update();
|
|
switch ( ugcStatus )
|
|
{
|
|
case UGCFILEREQUEST_ERROR:
|
|
{
|
|
Warning("An error occurred while attempting to download a file from the UGC server!\n");
|
|
// Msg("- Deleted: %llu\tPriority:%u\tTimestamp:%u\n", pFileRequest->fileHandle, pFileRequest->unPriority, pFileRequest->unTimestamp );
|
|
m_PendingFileOperations.RemoveAtHead();
|
|
}
|
|
break;
|
|
|
|
case UGCFILEREQUEST_FINISHED:
|
|
{
|
|
// If we finished an upload, we need to move the file over into the main library
|
|
// FIXME: The library is usually downloaded files ready on disk. Now it means things in the clouds or things on disk...
|
|
if ( pFileRequest->nType == UGC_REQUEST_UPLOAD )
|
|
{
|
|
// If this is invalid, we didn't capture our final file handle properly
|
|
Assert( pFileRequest->fileRequest.GetCloudHandle() != k_UGCHandleInvalid );
|
|
if ( pFileRequest->fileRequest.GetCloudHandle() != k_UGCHandleInvalid )
|
|
{
|
|
pFileRequest->fileHandle = pFileRequest->fileRequest.GetCloudHandle();
|
|
// Add this into the main list now that it's completed
|
|
m_FileRequests.Insert( pFileRequest->fileHandle, pFileRequest );
|
|
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCRequestManager] Finished uploading %llu\n", pFileRequest->fileHandle );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCRequestManager] Finished downloading %llu\n", pFileRequest->fileHandle );
|
|
|
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "ugc_file_download_finished" );
|
|
if ( pEvent )
|
|
{
|
|
pEvent->SetUint64( "hcontent", pFileRequest->GetFileHandle() );
|
|
gameeventmanager->FireEventClientSide( pEvent );
|
|
}
|
|
}
|
|
|
|
// We're done, continue on!
|
|
// Msg("- Deleted: %llu\tPriority:%u\tTimestamp:%u\n", pFileRequest->fileHandle, pFileRequest->unPriority, pFileRequest->unTimestamp );
|
|
m_PendingFileOperations.RemoveAtHead();
|
|
}
|
|
break;
|
|
|
|
case UGCFILEREQUEST_READY:
|
|
{
|
|
if ( pFileRequest->nType == UGC_REQUEST_DOWNLOAD )
|
|
{
|
|
// Pass along target directory and filename unless they're not set
|
|
const char *lpszTargetDirectory = ( pFileRequest->szTargetDirectory[0] != '\0' ) ? pFileRequest->szTargetDirectory : NULL;
|
|
const char *lpszTargetFilename = ( pFileRequest->szTargetFilename[0] != '\0' ) ? pFileRequest->szTargetFilename : NULL;
|
|
|
|
// We're ready to download, so start us off
|
|
UGCFileRequestStatus_t status = pFileRequest->fileRequest.StartDownload( pFileRequest->fileHandle, lpszTargetDirectory, lpszTargetFilename, pFileRequest->unLastUpdateTime, pFileRequest->bForceUpdate );
|
|
if ( status == UGCFILEREQUEST_FINISHED )
|
|
{
|
|
// We're already done (file was on disk)
|
|
// FIXME: Roll this into the function call above!
|
|
// Msg("- Deleted: %llu\tPriority:%u\tTimestamp:%u\n", pFileRequest->fileHandle, pFileRequest->unPriority, pFileRequest->unTimestamp );
|
|
m_PendingFileOperations.RemoveAtHead();
|
|
}
|
|
|
|
|
|
if ( status == UGCFILEREQUEST_DOWNLOADING )
|
|
{
|
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "ugc_file_download_start" );
|
|
if ( pEvent )
|
|
{
|
|
pEvent->SetUint64( "hcontent", pFileRequest->GetFileHandle() );
|
|
pEvent->SetUint64( "published_file_id", pFileRequest->GetPublishedFileID() );
|
|
gameeventmanager->FireEventClientSide( pEvent );
|
|
}
|
|
}
|
|
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCRequestManager] Beginning download of %llu\n", pFileRequest->fileHandle );
|
|
|
|
return;
|
|
}
|
|
else if ( pFileRequest->nType == UGC_REQUEST_UPLOAD )
|
|
{
|
|
const char *lpszTargetDirectory = ( pFileRequest->szTargetDirectory[0] != '\0' ) ? pFileRequest->szTargetDirectory : NULL;
|
|
const char *lpszTargetFilename = ( pFileRequest->szTargetFilename[0] != '\0' ) ? pFileRequest->szTargetFilename : NULL;
|
|
|
|
char szFullPath[MAX_PATH];
|
|
V_SafeComposeFilename( lpszTargetDirectory, lpszTargetFilename, szFullPath, ARRAYSIZE(szFullPath) );
|
|
|
|
// FIXME: Bleh, this makes all kinds of contracts we don't like!
|
|
CUtlBuffer buffer;
|
|
// FIXME: Swap for an async read!
|
|
if ( !g_pFullFileSystem->ReadFile( pFileRequest->szSourceFilename, "GAME", buffer ) )
|
|
{
|
|
// We failed to read this off the disk
|
|
buffer.Purge();
|
|
pFileRequest->fileRequest.ThrowError( "Unable to read file: %s\n", pFileRequest->szSourceFilename );
|
|
return;
|
|
}
|
|
|
|
// We're ready to download, so start us off
|
|
UGCFileRequestStatus_t status = pFileRequest->fileRequest.StartUpload( buffer, szFullPath );
|
|
if ( status == UGCFILEREQUEST_ERROR )
|
|
{
|
|
// FIXME: Now what?
|
|
// m_PendingFileOperations.RemoveAtHead();
|
|
Assert( 0 );
|
|
}
|
|
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCRequestManager] Beginning upload of %s\n", szFullPath );
|
|
|
|
// Done with the memory
|
|
buffer.Purge();
|
|
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// Working, continue to wait...
|
|
return;
|
|
break;
|
|
}
|
|
|
|
// The request is complete, continue to the next!
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CUGCFileRequestManager::CreateFileDownloadRequest( UGCHandle_t unFileHandle, PublishedFileId_t fileID, const char *lpszTargetDirectory, const char *lpszTargetFilename, uint32 unPriority, uint32 unLastUpdateTime /*=0*/, bool bForceUpdate /*= false*/ )
|
|
{
|
|
// Must pass in a valid handle if we're downloading
|
|
if ( unFileHandle == k_UGCHandleInvalid )
|
|
return false;
|
|
|
|
// Make sure we don't already have a request by this handle
|
|
if ( FileRequestExists( unFileHandle ) )
|
|
return true;
|
|
|
|
UGCFileRequest_t *pRequest = new UGCFileRequest_t;
|
|
pRequest->nType = UGC_REQUEST_DOWNLOAD;
|
|
pRequest->fileHandle = unFileHandle;
|
|
pRequest->publishedFileID = fileID;
|
|
|
|
if ( lpszTargetDirectory != NULL )
|
|
{
|
|
V_strncpy( pRequest->szTargetDirectory, lpszTargetDirectory, ARRAYSIZE(pRequest->szTargetDirectory) );
|
|
V_FixSlashes( pRequest->szTargetDirectory );
|
|
}
|
|
|
|
if ( lpszTargetFilename != NULL )
|
|
{
|
|
V_strncpy( pRequest->szTargetFilename, lpszTargetFilename, ARRAYSIZE(pRequest->szTargetFilename) );
|
|
}
|
|
|
|
pRequest->unLastUpdateTime = unLastUpdateTime;
|
|
pRequest->bForceUpdate = bForceUpdate;
|
|
pRequest->unTimestamp = g_TimeStampIncr++; // FIXME: This is to get around some timestamping, in essence larger numbers = newer additions
|
|
pRequest->unPriority = unPriority;
|
|
|
|
// This insert will sort the request into the list properly
|
|
m_PendingFileOperations.Insert( pRequest );
|
|
|
|
// For debugging insertion into priority queue
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCFileRequestManager] Inserted Download: %llu\tPriority:%u\tTimestamp:%u\n", pRequest->fileHandle, pRequest->unPriority, pRequest->unTimestamp );
|
|
Debug_LogPendingOperations();
|
|
|
|
// Keep this in our records now
|
|
m_FileRequests.Insert( unFileHandle, pRequest );
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CUGCFileRequestManager::CreateFileUploadRequest( const char *lpszSourceFilename, const char *lpszTargetDirectory, const char *lpszTargetFilename, uint32 unPriority )
|
|
{
|
|
if ( lpszSourceFilename == NULL )
|
|
return false;
|
|
|
|
// Make sure we don't already have a request for this
|
|
char szFullPath[MAX_PATH];
|
|
V_SafeComposeFilename( lpszTargetDirectory, lpszTargetFilename, szFullPath, ARRAYSIZE(szFullPath) );
|
|
|
|
// Make sure we don't have another upload by the same filename in progress
|
|
const UGCFileRequest_t *pDuplicateRequest = GetFileRequestByFilename( szFullPath );
|
|
if ( pDuplicateRequest != NULL && pDuplicateRequest->nType == UGC_REQUEST_UPLOAD )
|
|
return true;
|
|
|
|
UGCFileRequest_t *pRequest = new UGCFileRequest_t;
|
|
pRequest->nType = UGC_REQUEST_UPLOAD;
|
|
pRequest->fileHandle = k_UGCHandleInvalid;
|
|
|
|
if ( lpszTargetDirectory != NULL )
|
|
{
|
|
V_strncpy( pRequest->szTargetDirectory, lpszTargetDirectory, ARRAYSIZE(pRequest->szTargetDirectory) );
|
|
V_FixSlashes( pRequest->szTargetDirectory );
|
|
}
|
|
|
|
if ( lpszTargetFilename != NULL )
|
|
{
|
|
V_strncpy( pRequest->szTargetFilename, lpszTargetFilename, ARRAYSIZE(pRequest->szTargetFilename) );
|
|
}
|
|
|
|
// Save where we're going to read from
|
|
V_strncpy( pRequest->szSourceFilename, lpszSourceFilename, ARRAYSIZE(pRequest->szSourceFilename) );
|
|
V_FixSlashes( pRequest->szSourceFilename );
|
|
|
|
pRequest->unLastUpdateTime = 0;
|
|
pRequest->bForceUpdate = false;
|
|
pRequest->unTimestamp = g_TimeStampIncr++; // FIXME: This is to get around some timestamping, in essence larger numbers = newer additions
|
|
pRequest->unPriority = unPriority;
|
|
|
|
// This insert will sort the request into the list properly
|
|
m_PendingFileOperations.Insert( pRequest );
|
|
|
|
// For debugging insertion into priority queue
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCFileRequestManager] Inserted Upload: %llu\tPriority:%u\tTimestamp:%u\n", pRequest->fileHandle, pRequest->unPriority, pRequest->unTimestamp );
|
|
Debug_LogPendingOperations();
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
const UGCFileRequest_t *CUGCFileRequestManager::GetFileRequestByHandle( UGCHandle_t unFileHandle ) const
|
|
{
|
|
int nIndex = m_FileRequests.Find( unFileHandle );
|
|
if ( nIndex == m_FileRequests.InvalidIndex() )
|
|
return NULL;
|
|
|
|
return m_FileRequests[nIndex];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CUGCFileRequestManager::FileRequestExists( UGCHandle_t handle ) const
|
|
{
|
|
int nIndex = m_FileRequests.Find( handle );
|
|
return ( nIndex != m_FileRequests.InvalidIndex() );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CUGCFileRequestManager::GetFullPath( UGCHandle_t unFileHandle, char *pDest, size_t nSize ) const
|
|
{
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( unFileHandle );
|
|
if ( pRequest == NULL )
|
|
{
|
|
// Clear the return so it's obvious it failed
|
|
V_memset( pDest, 0, nSize );
|
|
return;
|
|
}
|
|
|
|
pRequest->fileRequest.GetFullPath( pDest, nSize );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
const char *CUGCFileRequestManager::GetDirectory( UGCHandle_t unFileHandle ) const
|
|
{
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( unFileHandle );
|
|
if ( pRequest == NULL )
|
|
return NULL;
|
|
|
|
return pRequest->fileRequest.GetDirectory();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
const char *CUGCFileRequestManager::GetFilename( UGCHandle_t unFileHandle ) const
|
|
{
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( unFileHandle );
|
|
if ( pRequest == NULL )
|
|
return NULL;
|
|
|
|
return pRequest->fileRequest.GetFilename();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
UGCFileRequestStatus_t CUGCFileRequestManager::GetStatus( UGCHandle_t unFileHandle ) const
|
|
{
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( unFileHandle );
|
|
if ( pRequest == NULL )
|
|
return UGCFILEREQUEST_INVALID;
|
|
|
|
return pRequest->fileRequest.GetStatus();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Get the file handle for a request by its target filename
|
|
//-----------------------------------------------------------------------------
|
|
UGCHandle_t CUGCFileRequestManager::GetFileRequestHandleByFilename( const char *lpszFilename ) const
|
|
{
|
|
// Get the request by name
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByFilename( lpszFilename );
|
|
if ( pRequest != NULL )
|
|
{
|
|
return pRequest->fileHandle;
|
|
}
|
|
|
|
return k_UGCHandleInvalid;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Get the file handle for a request by its target filename
|
|
//-----------------------------------------------------------------------------
|
|
const UGCFileRequest_t *CUGCFileRequestManager::GetFileRequestByFilename( const char *lpszFilename ) const
|
|
{
|
|
// FIXME: This is a slow crawl through a list doing stricmps :(
|
|
char szFullPath[MAX_PATH];
|
|
for ( unsigned int i=0; i < m_FileRequests.Count(); i++ )
|
|
{
|
|
const UGCFileRequest_t *pRequest = m_FileRequests[i];
|
|
pRequest->fileRequest.GetFullPath( szFullPath, ARRAYSIZE(szFullPath) );
|
|
if ( !V_stricmp( szFullPath, lpszFilename ) )
|
|
return pRequest;
|
|
}
|
|
|
|
// Now move through all the pending operations to see if it's living in there
|
|
// We need to do this because uploads don't live in the normal system until they're done uploading
|
|
// FIXME: This is going to be doing duplicate work since items can straddle both the known requests and the pending ones
|
|
for ( int i=0; i < m_PendingFileOperations.Count(); i++ )
|
|
{
|
|
const UGCFileRequest_t *pRequest = m_PendingFileOperations.Element(i);
|
|
pRequest->fileRequest.GetFullPath( szFullPath, ARRAYSIZE(szFullPath) );
|
|
if ( !V_stricmp( szFullPath, lpszFilename ) )
|
|
return pRequest;
|
|
}
|
|
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
UGCFileRequestStatus_t CUGCFileRequestManager::GetStatus( const char *lpszFilename ) const
|
|
{
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByFilename( lpszFilename );
|
|
if ( pRequest == NULL )
|
|
return UGCFILEREQUEST_INVALID;
|
|
|
|
return pRequest->fileRequest.GetStatus();
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Returns the progress of a file being downloaded from the Steam cloud.
|
|
// Return: Always 0 if nothing has begun, or 1 if past the point of downloading, otherwise, the percentage downloaded
|
|
//-----------------------------------------------------------------------------
|
|
float CUGCFileRequestManager::GetDownloadProgress( UGCHandle_t handle ) const
|
|
{
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( handle );
|
|
if ( pRequest == NULL )
|
|
return 0.0f;
|
|
|
|
return pRequest->GetProgress();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Promote the specified handle to the top of the priority list
|
|
//-----------------------------------------------------------------------------
|
|
bool CUGCFileRequestManager::PromoteRequestToTop( UGCHandle_t handle )
|
|
{
|
|
// The request must be in the system
|
|
const UGCFileRequest_t *pRequest = GetFileRequestByHandle( handle );
|
|
if ( pRequest == NULL )
|
|
return false;
|
|
|
|
// There must be pending operations to bother continuing
|
|
if ( m_PendingFileOperations.Count() == 0 )
|
|
return false;
|
|
|
|
// If we're already at the top, don't bother
|
|
const UGCFileRequest_t *pTopRequest = m_PendingFileOperations.ElementAtHead();
|
|
if ( pTopRequest == pRequest )
|
|
return true;
|
|
|
|
// This is the top priority currently
|
|
uint32 unTopPriority = pTopRequest->unPriority;
|
|
|
|
// Now we need to find this request in the pending operations
|
|
for ( int i = 0; i < m_PendingFileOperations.Count(); i++ )
|
|
{
|
|
const UGCFileRequest_t *pFoundRequest = m_PendingFileOperations.Element(i);
|
|
if ( pRequest == pFoundRequest )
|
|
{
|
|
// Bump our priority up
|
|
// We cast away the const reference because we're the controlling class for this type
|
|
((UGCFileRequest_t *)pRequest)->unPriority = unTopPriority+1;
|
|
m_PendingFileOperations.RemoveAt(i);
|
|
m_PendingFileOperations.Insert( ((UGCFileRequest_t *)pRequest) );
|
|
Log_Msg( LOG_WORKSHOP, "[CUGCFileRequestManager] Promoted %llu to top of queue\n", pRequest->fileHandle );
|
|
Debug_LogPendingOperations();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Dump our priority queue so we can debug it
|
|
//-----------------------------------------------------------------------------
|
|
void CUGCFileRequestManager::Debug_LogPendingOperations( void )
|
|
{
|
|
#if 0
|
|
// Must have something to operate on
|
|
if ( m_PendingFileOperations.Count() == 0 )
|
|
return;
|
|
|
|
// For debugging insertion into priority queue
|
|
Log_Msg( LOG_WORKSHOP, "\n==[Pending UGC Operations]==\n");
|
|
|
|
// The queue cannot be walked through trivially, so we need to actually pop each member off the top, the reinsert at the end
|
|
CUtlVector< UGCFileRequest_t * > vecOverflow;
|
|
while ( m_PendingFileOperations.Count() )
|
|
{
|
|
UGCFileRequest_t *pQueuedRequest = m_PendingFileOperations.ElementAtHead();
|
|
Log_Msg( LOG_WORKSHOP, "o File: %llu\tPriority:%u\tTimestamp:%u\n", pQueuedRequest->fileHandle, pQueuedRequest->unPriority, pQueuedRequest->unTimestamp );
|
|
vecOverflow.AddToTail( pQueuedRequest );
|
|
m_PendingFileOperations.RemoveAtHead();
|
|
}
|
|
|
|
// Put them all back
|
|
for ( int i=0; i < vecOverflow.Count(); i++ )
|
|
{
|
|
m_PendingFileOperations.Insert( vecOverflow[i] );
|
|
}
|
|
|
|
Log_Msg( LOG_WORKSHOP, "==============================\n\n");
|
|
#endif //
|
|
}
|
|
|
|
bool CUGCFileRequestManager::HasPendingDownloads( void ) const
|
|
{
|
|
return m_PendingFileOperations.Count() > 0;
|
|
}
|
|
|
|
#endif // ! NO_STEAM
|